#include <sdk/manager.h>

IMPLEMENT_DYNAMIC(listview, CListCtrl)

BEGIN_MESSAGE_MAP(listview, CListCtrl)
	ON_NOTIFY_REFLECT(NM_CLICK, &listview::OnNMClick)
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &listview::OnNMCustomdraw)
	ON_NOTIFY_REFLECT(LVN_ITEMCHANGING, &listview::OnLvnItemchanging)
	ON_NOTIFY_REFLECT(LVN_GETDISPINFO, &listview::OnLvnGetdispinfo)
	ON_NOTIFY_REFLECT(LVN_ITEMACTIVATE, &listview::OnLvnItemActivate)
	ON_WM_MEASUREITEM_REFLECT()
END_MESSAGE_MAP()

void listview::create(CRect& _rect, CWnd* _parent, UINT _msg_id)
{
	Create(WS_CHILD|WS_VISIBLE|LVS_NOSORTHEADER|LVS_REPORT,
		_rect, _parent, _msg_id);

	SetExtendedStyle(GetExtendedStyle()
		| LVS_EX_FULLROWSELECT
		| LVS_EX_GRIDLINES);

	initial();
}

void listview::click_item(LPNMITEMACTIVATE _item)
{
	list_column& _col = get_column(_item->iSubItem);
	if(_col.ctype == ct_check)
	{
		CRect rect;
		GetSubItemRect(_item->iItem, _item->iSubItem, LVIR_BOUNDS, rect);
		int offset_half = (rect.Width()-rect.Height())/2;
		rect.left+=offset_half;
		rect.right-=offset_half;
		bool hit = rect.PtInRect(_item->ptAction) == TRUE;
		if(hit)
		{
			if(on_click_item(_item->iItem, _item->iSubItem))
				Invalidate(NULL);
		}
	}
	else
	{
		if(on_click_item(_item->iItem, _item->iSubItem))
			Invalidate(NULL);
	}
}

void listview::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLVCUSTOMDRAW pNMCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
	// TODO: Add your control notification handler code here

	
	switch(pNMCD->nmcd.dwDrawStage)
	{
	default:				*pResult = 0; break;
	case CDDS_PREPAINT:		*pResult = CDRF_NOTIFYITEMDRAW;	break;
	case CDDS_ITEMPREPAINT:
		*pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYSUBITEMDRAW;
		{
			on_color_column_bk(pNMCD->nmcd.dwItemSpec, pNMCD->clrTextBk);

			CRect rect,wrc;
			GetWindowRect(wrc);
			GetItemRect(pNMCD->nmcd.dwItemSpec, rect,  LVIR_BOUNDS);
			rect.right = rect.left + wrc.Width();
			::FillRect(pNMCD->nmcd.hdc, rect, CBrush(pNMCD->clrTextBk));
		}
		break;
	case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
		*pResult = draw_subitem(pNMCD) ? CDRF_SKIPDEFAULT : 0;
		break;
	}
}

bool listview::draw_subitem(LPNMLVCUSTOMDRAW _cd)
{
	int item_id =  _cd->nmcd.dwItemSpec;
	
	if( get_column(_cd->iSubItem).ctype == ct_check)
	{
		CRect rect;
		GetSubItemRect(item_id, _cd->iSubItem, LVIR_BOUNDS ,rect);
		::DrawFrameControl(_cd->nmcd.hdc, rect, DFC_BUTTON,
			on_column_check(item_id, _cd->iSubItem) ? DFCS_CHECKED : DFCS_BUTTONCHECK);

		return true;
	}
	else
	{
		on_color_column_text(item_id, _cd->iSubItem, _cd->clrText);
		on_color_column_bk(_cd->iSubItem, _cd->clrTextBk);
		return false;
	}
	
}

void listview::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	lpMeasureItemStruct->itemHeight = 100;
}

void listview::PreSubclassWindow()
{
	CRect rcwin;  
	GetWindowRect(rcwin);  

	WINDOWPOS wp;  
	wp.hwnd=GetSafeHwnd();  
	wp.cx=rcwin.Width();  
	wp.cy=rcwin.Height();  
	wp.flags=SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER;  
	SendMessage(WM_WINDOWPOSCHANGED,0,(LPARAM)&wp);  
}

void listview::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: Add your control notification handler code here

	click_item(pNMItemActivate);
	
	*pResult = 0;
}

void listview::OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	// TODO: Add your control notification handler code here
	
	// is the user selecting an item?
    if ((pNMLV->uChanged & LVIF_STATE) && (pNMLV->uNewState & LVNI_SELECTED))
    {
        // yes - never allow a selected item
        *pResult = 1;
		return;
    }

	*pResult = 0;
}

BOOL listview::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO: Add your specialized code here and/or call the base class
	NMHDR* pNMHdr = (NMHDR*) lParam;

	if(pNMHdr->hwndFrom == GetHeaderCtrl()->GetSafeHwnd())
	{
		switch(pNMHdr->code)
		{
		case HDN_DIVIDERDBLCLICKA:
		case HDN_DIVIDERDBLCLICKW:
		case HDN_BEGINTRACKA:
		case HDN_BEGINTRACKW:
			
			if(get_column(((LPNMHEADER)pNMHdr)->iItem).is_fix)
			{
				*pResult = TRUE;
				return TRUE;
			}
			
			break;
		}
	}

	return CListCtrl::OnNotify(wParam, lParam, pResult);
	
}

void listview::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
	// TODO: Add your control notification handler code here
	list_column& col = get_column(pDispInfo->item.iSubItem);
	switch(col.ctype)
	{
	case ct_check:
		break;
	case ct_text:
		pDispInfo->item.pszText = (char*)on_column_text(pDispInfo->item.iItem, pDispInfo->item.iSubItem);
		break;
	}
	
	*pResult = 0;
}

void listview::OnLvnItemActivate(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: Add your control notification handler code here
	
	if(on_double_click_item(pNMIA->iItem, pNMIA->iSubItem))
	{
		InvalidateRect(NULL);
	}
	*pResult = 0;
}
